home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Moving Worlds - Companion
/
Moving Worlds.iso
/
obj2wrl
/
obj2wrl
< prev
next >
Wrap
Text File
|
1995-06-22
|
15KB
|
526 lines
#!/usr/local/apps/perl/bin/perl
#############################################################################
# #
# WHO: John L. Moreland #
# #
# WHAT: obj2wrl #
# #
# WHY: Converts a wavefront OBJ file to a VRML file. #
# #
# WHERE: San Diego Supercomputer Center (SDSC) #
# #
# WHEN: Wed Mar 15 13:00:23 PST 1995 (ORIGINAL) #
# Tue Apr 11 10:15:36 PST 1995 (CURRENT) #
# #
# HOW: Perl #
# #
#############################################################################
# #
# Copyright (c) 1995 San Diego Supercomputer Center (SDSC) #
# a division of General Atomics, San Diego, California, USA #
# #
# Users and possessors of this source code are hereby granted a #
# nonexclusive, royalty-free copyright and design patent license to #
# use this code in individual software. License is not granted for #
# commercial resale, in whole or in part, without prior written #
# permission from SDSC. This source is provided "AS IS" without #
# express or implied warranty of any kind. #
# #
# For further information contact: #
# E-Mail: info@sds.sdsc.edu #
# #
# Surface Mail: Information Center #
# San Diego Supercomputer Center #
# P.O. Box 85608 #
# San Diego, CA 92138-5608 #
# (619) 534-5000 #
# #
#############################################################################
#############################################################################
################################ SUBROUTINES ##############################
#############################################################################
#############################################################################
# #
# Returns the maximum of all values passed in. #
# #
#############################################################################
sub max
{
local( $result ) = pop( @_ );
foreach $item ( @_ )
{
$result = $item if $item > $result;
}
return( $result );
}
#############################################################################
# #
# Returns the minimum of all values passed in. #
# #
#############################################################################
sub min
{
local( $result ) = pop( @_ );
foreach $item ( @_ )
{
$result = $item if $item < $result;
}
return( $result );
}
#############################################################################
# #
# Returns the absolute value of the number passed in. #
# #
#############################################################################
sub abs
{
local( $result ) = $_[0];
$result *= -1 if $result < 0;
return( $result );
}
#############################################################################
################################### INIT ##################################
#############################################################################
#############################################################################
# SET DEFAULT VARIABLE VALUES
$nLines = 0; # Number of lines read from input file
$nVerts = 0; # Number of verticies parsed out of the input file
$nPolys = 0; # Number of face-sets parsed out of the input file
$nSNorms = 0; # Number of surface-normals parsed out of the input file
$nTNorms = 0; # Number of texture-normals parsed out of the input file
$input_name = "STDIN"; # The input file name
$output_name = "STDOUT"; # The output file name
$verbose_name = "/dev/null"; # The verbose-message file name
$x_max = ""; # Max of all X-Coordinate vertex values
$x_min = ""; # Min of all X-Coordinate vertex values
$y_max = ""; # Max of all Y-Coordinate vertex values
$y_min = ""; # Min of all Y-Coordinate vertex values
$z_max = ""; # Max of all Z-Coordinate vertex values
$z_min = ""; # Min of all Z-Coordinate vertex values
$x_range = 0.0; # MaxX - MinX
$x_center = 0.0; # (MaxX+MinX)/2
$y_range = 0.0; # MaxY - MinY
$y_center = 0.0; # (MaxY+MinY)/2
$z_range = 0.0; # MaxZ - MinZ
$z_center = 0.0; # (MaxZ+MinZ)/2
$data_max = 0.0; # MAX OF x_max, y_max, z_max
$data_min = 0.0; # MIN OF x_max, y_max, z_max
$data_center = 0.0;
$data_range = 0.0;
$normalize = 0; # Should we normalize the data ? (default=NO)
$x_scale = 1.0; # Scale factor for X-Axis
$y_scale = 1.0; # Scale factor for Y-Axis
$z_scale = 1.0; # Scale factor for Z-Axis
$colorize = 0; # Should we color the data by depth ? (default=NO)
#############################################################################
# PARSE COMMAND LINE
while ( @ARGV )
{
$option = shift( @ARGV );
if ( $option eq "-infile" )
{
$input_name = shift( @ARGV );
}
elsif ( $option eq "-outfile" )
{
$output_name = shift( @ARGV );
}
elsif ( $option eq "-verbose" )
{
$verbose_name = "STDERR";
}
elsif ( $option eq "-normalize" )
{
$normalize = 1;
}
elsif ( $option eq "-colorize" )
{
$colorize = 1;
}
elsif ( $option eq "-xscale" )
{
$x_scale = shift( @ARGV );
}
elsif ( $option eq "-yscale" )
{
$y_scale = shift( @ARGV );
}
elsif ( $option eq "-zscale" )
{
$z_scale = shift( @ARGV );
}
elsif ( ! ( $option =~ /^-/ ) )
{
# Allow input and output file names to be specified
# without the lame option flags. Just parse filenames out.
if ( $input_name eq "STDIN" )
{
if ( ! -f $option )
{
print STDERR "Infile does not exist: $option\n";
exit( 1 );
}
$input_name = $option;
}
elsif ( $output_name eq "STDOUT" )
{
$output_name = $option;
}
else
{
print STDERR "Too many files specified: $option\n";
exit( 1 );
}
}
else
{
print STDERR "Unknown option $option\n";
print STDERR "Usage: $0 [arguments]\n";
print STDERR " [-infile inputfile]\n";
print STDERR " default is STDIN\n";
print STDERR " [-outfile outputfile]\n";
print STDERR " default is STDOUT\n";
print STDERR " -verbose\n";
print STDERR " default is OFF\n";
print STDERR " -normalize\n";
print STDERR " default is OFF\n";
print STDERR " -colorize\n";
print STDERR " default is OFF\n";
print STDERR " -xscale float\n";
print STDERR " default is 1.0\n";
print STDERR " -yscale float\n";
print STDERR " default is 1.0\n";
print STDERR " -zscale float\n";
print STDERR " default is 1.0\n";
exit( 1 );
}
}
if ( $input_name eq "STDIN" )
{
open( INPUT, "<&STDIN" );
}
else
{
open( INPUT, "<$input_name" );
}
if ( $output_name eq "STDOUT" )
{
open( OUTPUT, ">&STDOUT" );
}
else
{
open( OUTPUT, ">$output_name" );
}
if ( $verbose_name eq "STDERR" )
{
open( VERBOSE, ">&STDERR" );
}
else
{
open( VERBOSE, ">$verbose_name" );
}
print VERBOSE "Using $input_name for input and $output_name for output...\n";
#############################################################################
################################### MAIN ##################################
#############################################################################
#############################################################################
# READ THE FILE INTO OUR "OBJ" LIST
print VERBOSE "Reading $input_name... ";
@OBJ = <INPUT>;
$nLines = $#OBJ + 1;
print VERBOSE "($nLines lines read)\n";
close( INPUT );
#############################################################################
# PARSE OUT: VERTICIES, POLYGONS, SURFACE NORMALS, AND TEXTURE NORMALS
print VERBOSE "Extracting data...\n";
for ( $i=0; $i<$nLines; $i++ )
{
chop( $line = $OBJ[$i] );
next if ( $line =~ /^#/ ); # Skip comments
next if ( $line =~ /^$/ ); # Skip blank lines
if ( $line =~ /^v / )
{
( $v, $x, $y, $z, @junk ) = split( /\s+/, $line );
$vertices{$nVerts} = join( " ", $x, $y, $z );
if ( $x_max eq "" )
{
$x_max = $x;
$x_min = $x;
$y_max = $y;
$y_min = $y;
$z_max = $z;
$z_min = $z;
}
else
{
$x_max = &max( $x_max, $x );
$x_min = &min( $x_min, $x );
$y_max = &max( $y_max, $y );
$y_min = &min( $y_min, $y );
$z_max = &max( $z_max, $z );
$z_min = &min( $z_min, $z );
}
$nVerts++;
}
elsif ( $line =~ /^f / )
{
@temp1 = split( /\s+/, $line );
shift( @temp1 ); # Toss the "f "
@temp2 = ();
for ( $j=0; $j<=$#temp1; $j++ )
{
( $index, @junk ) = split( /\//, $temp1[$j] );
$index -= 1;
if ( $input_name =~ /eel/ ) { $index += 1; } # HACK
@temp2 = ( @temp2, $index );
}
$connections{$nPolys} = join( " ", @temp2 );
$nPolys++;
}
elsif ( $line =~ /^vt / )
{
}
elsif ( $line =~ /^vn / )
{
}
else
{
}
}
print VERBOSE " Verticies: $nVerts\n";
print VERBOSE " Polygons: $nPolys\n";
#############################################################################
# CALCULATE DATA STATISTICS
print VERBOSE "Calculating data statistics...\n";
$x_range = &abs( $x_max - $x_min );
$x_center = ($x_max + $x_min) / 2.0;
$y_range = &abs( $y_max - $y_min );
$y_center = ($y_max + $y_min) / 2.0;
$z_range = &abs( $z_max - $z_min );
$z_center = ($z_max + $z_min) / 2.0;
$data_max = &max( $x_max, $y_max, $z_max );
$data_min = &min( $x_min, $y_min, $z_min );
$data_center = ($data_max + $data_min) / 2.0;
$data_range = &max( $x_range, $y_range, $z_range );
$normalization = $data_range / 2.0;
print VERBOSE " x_max = $x_max\n";
print VERBOSE " x_min = $x_min\n";
print VERBOSE " x_center = $x_center\n";
print VERBOSE " x_range = $x_range\n";
print VERBOSE "\n";
print VERBOSE " y_max = $y_max\n";
print VERBOSE " y_min = $y_min\n";
print VERBOSE " y_center = $y_center\n";
print VERBOSE " y_range = $y_range\n";
print VERBOSE "\n";
print VERBOSE " z_max = $z_max\n";
print VERBOSE " z_min = $z_min\n";
print VERBOSE " z_center = $z_center\n";
print VERBOSE " z_range = $z_range\n";
print VERBOSE "\n";
print VERBOSE " data_max = $data_max\n";
print VERBOSE " data_min = $data_min\n";
print VERBOSE " data_center = $data_center\n";
print VERBOSE " data_range = $data_range\n";
print VERBOSE "Done calculating data statistics.\n";
#############################################################################
# WRITE VRML
print VERBOSE "Writting $output_name...\n";
print OUTPUT "#VRML V1.0 ascii\n";
print OUTPUT "\n";
print OUTPUT "Separator {\n";
print OUTPUT "\tSeparator {\n";
print OUTPUT "\t\tTransform { rotation -1 0 0 3.0 }\n";
# print OUTPUT "\t\tLightModel { model BASE_COLOR }\n";
if ( $colorize )
{
print OUTPUT "\t\tMaterialBinding { value PER_VERTEX_INDEXED }\n";
#####################################################################
# WRITE MATERIAL TABLE
print OUTPUT "\t\tMaterial {\n";
print OUTPUT "\t\t\tdiffuseColor [\n";
for ( $i=0; $i<$nVerts; $i++ )
{
# DEREFERENCE A VERTICY
@vert = split( /\s+/, $vertices{$i} );
# COLORIZE THE DATA
if ( $z_range != 0 ) { $vert[2] /= ($z_range / 2.0); }
$red = 0.0;
$green = 1.0-$vert[2]/-1.5;
$blue = 0.5+$vert[2]/-1.5;
if ( $vert[2] == 0.0 )
{
$red = 0.0;
$green = 0.25;
$blue = 0.0;
}
# OUTPUT THE DATA
print OUTPUT "\t\t\t\t";
printf( OUTPUT "%f %f %f", $red, $green, $blue );
if ( $i == $nVerts - 1 )
{
print OUTPUT "\n";
} else {
print OUTPUT ",\n";
}
}
printf OUTPUT "\t\t\t]\n";
printf OUTPUT "\t\t}\n";
}
#############################################################################
# WRITE VERTEXT DATA
print OUTPUT "\t\tCoordinate3 {\n";
print OUTPUT "\t\t\tpoint [\n";
for ( $i=0; $i<$nVerts; $i++ )
{
# DEREFERENCE A VERTICY
@vert = split( /\s+/, $vertices{$i} );
if ( $normalize == 1 )
{
# CENTER THE DATA
$vert[0] -= $x_center;
$vert[1] -= $y_center;
$vert[2] -= $z_center;
# NORMALIZE THE DATA
$vert[0] /= $normalization;
$vert[1] /= $normalization;
$vert[2] /= $normalization;
}
# SCALE THE DATA
if ( $x_scale != 1.0 ) { $vert[0] *= $x_scale; }
if ( $y_scale != 1.0 ) { $vert[1] *= $y_scale; }
if ( $z_scale != 1.0 ) { $vert[2] *= $z_scale; }
# OUTPUT THE DATA
print OUTPUT "\t\t\t\t";
printf( OUTPUT "%f %f %f", $vert[0], $vert[1], $vert[2] );
if ( $i == $nVerts - 1 )
{
print OUTPUT "\n";
} else {
print OUTPUT ",\n";
}
}
printf OUTPUT "\t\t\t]\n";
printf OUTPUT "\t\t}\n";
#############################################################################
# WRITE CONNECTIVITY DATA
print OUTPUT "\t\tIndexedFaceSet {\n";
print OUTPUT "\t\t\tcoordIndex [\n";
for ( $i=0; $i<$nPolys; $i++ )
{
# EXTRACT THE NEXT SET OF VERTICIES FOR A NEW QUAD
@cons = split( /\s+/, $connections{$i} );
print OUTPUT "\t\t\t\t";
for ( $j=0; $j<=$#cons; $j++ )
{
# $cons[$j] -= 1; ALREADY DONE IN EXTRACTION STEP
print OUTPUT "$cons[$j], ";
}
print OUTPUT "-1";
if ( $i == $nPolys - 1 )
{
print OUTPUT "\n";
} else {
print OUTPUT ",\n";
}
}
print OUTPUT "\t\t\t]\n";
print OUTPUT "\t\t}\n";
print OUTPUT "\t}\n";
#############################################################################
# DONE
print OUTPUT "}\n";
close( OUTPUT );
print VERBOSE "Done writting $output_name...\n";
print VERBOSE "Done\n";